package comman.duke 
{
	import flash.display.*;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	
	/**
	 * ...
	 * @author jerry.d
	 */
	public class ResourceLoader extends EventDispatcher 
	{
		public static var AtlasMap:Object = {};
		
		public static const TYPE_IMAGE:uint = 0;
		public static const TYPE_BINATY:uint = 1;
		public static const TYPE_TEXT:uint = 2;
		public static const TYPE_SPRITE_SHEET:uint = 99;
		public static const TYPE_GROUP:uint = 100;
		
		private var assets:Object;
		private var waitingQueue:Vector.<String>;
		private var loadingAssets:Object;
		private var callbacks:Object;
		private var typeMap:Object;
		private var groupMap:Object;
		
		public function ResourceLoader(target:flash.events.IEventDispatcher=null) 
		{
			super(target);
			this.assets = {};
			this.loadingAssets = {};
			this.callbacks = {};
			this.waitingQueue = new Vector.<String>();
			this.loaders = new Vector.<LoadItem>();
			this.typeMap = {};
			this.groupMap = {};
			var cnt:int = 5;
			while ( cnt > 0 ){
				this.loaders.push( new LoadItem);
				cnt--;
			}
		}
		
		private function checkGroupIsComplete(urls:Array):Boolean{
			for(var url:String in urls){
				if ( this.assets[url] == null ){
					return false;
				}
				
			}
			return true;
		}
		
		private function checkLoadingAndComplete(urls:Array):Boolean{
			for(var url:String in urls){
				if ( this.assets[url] == null && !this.loadingAssets[url] ){
					return false;
				}
				
			}
			return true;
		}
		
		private var currentGroup:uint = 0;
		public static const GROUP_NAME_PREFIX:String = "group_";
		private var loaders:Vector.<LoadItem>;
		/**
		 * urls:{url:String, type:uint}
		 * */
		public function load(urls:Array, callback:Function, groupName:String=""):void{
			
			if ( checkGroupIsComplete(urls) ){//load complete
				callback();
				return;
			}
			var groupName:String = groupName || (GROUP_NAME_PREFIX + currentGroup);
			currentGroup++;
			if ( this.checkLoadingAndComplete(urls) ){//loading 
				var arr:Array = this.callbacks[groupName];
				if ( arr.indexOf(callback) == -1){
					arr.push(callback);
				}
				return;
			}
			
			if ( this.waitingQueue.indexOf(groupName) != -1  ){//waiting
				arr = this.callbacks[groupName];
				if ( arr.indexOf(callback) == -1){
					arr.push(callback);
				}
				return;
			}else{
				this.groupMap[groupName] = urls;
				for each(var obj:* in urls){
					this.typeMap[obj.url] = obj.type;
				}
				//this.typeMap[groupName] = type;
				this.waitingQueue.push(groupName);
				this.callbacks[groupName] = [callback];
			}
			next();
		}
		
		private function next():void{
			if ( loaders.length != 0 && waitingQueue.length != 0){
				var loader:LoadItem = this.loaders.pop();
				var groupName:String = waitingQueue.pop();
				var group:Array = this.groupMap[groupName];
				loader.loadGroup(groupName,group);
			}
		}
		
		public function getResType(resName:String):uint{
			return this.typeMap[resName];
		}
		
		public function assetLoadComplete(loader:LoadItem):void{
			var assetName:String = loader.assetName;
			GameUtils.log("Asset Load Complete : ", assetName);
			var groupName:String = loader.groupName;
			this.assets[assetName] = loader.content;
		}
		
		public function loadComplete(loader:LoadItem):void{
			var resName:String = loader.groupName || loader.assetName;
			GameUtils.log("Load Complete : ",resName);
			if ( this.loaders.indexOf(loader) == -1){
				this.loaders.push(loader);
			}
			var callback:Array = this.callbacks[resName];
			
			for each(var fun:Function in callback){
				fun();
			}
			delete this.callbacks[resName];
			delete this.loadingAssets[resName];
			next();
		}
		
		public function getAsset(url:String):*{
			return this.assets[url];
		}
		
		
		private static var _instance:ResourceLoader;
		public static function get Instance():ResourceLoader{
			if ( ResourceLoader._instance == null){
				ResourceLoader._instance = new ResourceLoader();
			}
			return ResourceLoader._instance;
		}
		
	}

}